/*
 * @Author       : Thyssen Wen
 * @Date         : 2022-09-05 14:16:15
 * @LastEditors  : Thyssen Wen
 * @LastEditTime : 2022-09-06 09:05:19
 * @Description  : BookShelf Head File
 * @FilePath     : /cdesign-pattern/Iterator/BookShelf.h
 */
#pragma once
#include <vector>
#include "Iterator.h"
#include "Book.h"
#include "Aggregate.h"

template<class Item>
class BookShelf: public Aggregate <Item>
{
private:
    std::vector<Item> books;
    int last = 0;
public:
    BookShelf() {};
    BookShelf(int maxsize);
    ~BookShelf() {};

    Item& getBookAt(int index);
    Item& operator[](int index);
    void appendBook(Item book);
    int getLength();
    Iterator<Item>* iterator();
};

template<class Item>
class BookShelfIterator: public Iterator <Item>
{
private:
    BookShelf<Item> *bookshelf;
    int index;
public:
    BookShelfIterator(BookShelf<Item> *bookshelf);
    ~BookShelfIterator() {};
    bool hasNext();
    Item *next();
};

template<class Item>
BookShelfIterator<Item>::BookShelfIterator(BookShelf<Item> *bookshelf)
{
    this->bookshelf = bookshelf;
    this->index = 0;
}

template<class Item>
bool BookShelfIterator<Item>::hasNext()
{
    if (index < bookshelf->getLength())
    {
        return true;
    }else{
        return false;
    }
}

template<class Item>
Item* BookShelfIterator<Item>::next()
{
    Book book = bookshelf->getBookAt(index);
    index++;
    Book* book_ptr = & book;
    return book_ptr;
}

template<class Item>
BookShelf<Item>::BookShelf(int maxsize)
{
    std::vector<Item> data(4);
    this->books = data;
}

template<class Item>
Item& BookShelf<Item>::getBookAt(int index)
{
    return books[index];
}

template<class Item>
Item& BookShelf<Item>::operator[](int index)
{
    return books[index];
}

template<class Item>
void BookShelf<Item>::appendBook(Item book)
{
    this->books[last] = book;
    last++;
}

template<class Item>
int BookShelf<Item>::getLength()
{
    return last;
}

template<class Item>
Iterator<Item>* BookShelf<Item>::iterator()
{
    Iterator<Item> *bookshelf_iterator = new BookShelfIterator<Item>(this);
    return bookshelf_iterator;
}